#include "ListaEnlazada.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  TListaE::TListaE():longitud(0), primero(NULL) {}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  TListaE::TListaE(void *elementoNuevo) {
    primero  = new TNodo(elementoNuevo);
    longitud = 1;
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  TListaE::TListaE(TListaE * lista) {
    int longitud = lista->Longitud();
    if (!longitud) primero = NULL;
    else {
      primero       = new TNodo(lista->Obtener(0));
      TNodo *cursor = primero;
      for(int i = 1; i < longitud; i++) {
        TNodo *nuevoNodo = new TNodo(lista->Obtener(i));
        cursor->Next(nuevoNodo);
        cursor = nuevoNodo;
      }
    }
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  TListaE::~TListaE() {
    TNodo *cursor;
    while(primero) {
      cursor = primero;
      primero = primero->Next();
      delete cursor;
    }
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  TNodo* TListaE::PosNodo(int pos) {
    TNodo *cursor = primero;
    for (int i = 0; i < pos; i++)
      cursor = cursor->Next();
    return cursor;  
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  void TListaE::Anadir(void* elementoNuevo) {
    TNodo *nodoNuevo = new TNodo(elementoNuevo);
    TNodo *cursor    = primero;
    if (primero) {
      while (cursor->Next()) cursor = cursor->Next();
      cursor->Next(nodoNuevo);
    }
    else primero = nodoNuevo;
    longitud++;
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  void TListaE::Eliminar(int pos) {
    if ((pos < 0) || (pos >= longitud)) throw EListOutOfRange();
    TNodo *cursor = primero;
    if (!pos) primero = primero->Next();
    else {
      for (int i = 0; i < pos - 1; i++)
        cursor = cursor->Next();
      TNodo *nodoEliminar = cursor->Next();
      cursor->Next(nodoEliminar->Next());
      cursor = nodoEliminar;
    }
    delete cursor;
    longitud--;
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  void TListaE::Eliminar(void* valor) { 
    TNodo *cursor = primero, *temp = cursor;
    int pos = 0;
    while((cursor) && (cursor->Info() != valor)) {
      temp   = cursor;
      cursor = cursor->Next();
      pos++;
    }
    if (!pos) primero = primero->Next();
    else temp->Next(cursor->Next());
    delete cursor;
    longitud--;
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  void* TListaE::Transferir(int pos) {
    if ((pos < 0) || (pos >= longitud)) throw EListOutOfRange();
    TNodo *cursor = primero;
    if (!pos) primero = primero->Next();
    else {
      for (int i = 0; i < pos - 1; i++)
        cursor = cursor->Next();
      TNodo *nodoEliminar = cursor->Next();
      cursor->Next(nodoEliminar->Next());
      cursor = nodoEliminar;
    }
    longitud--;
    return cursor->Info();
  }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
  void TListaE::Insertar(void* elementoNuevo, int pos) {
    if ((pos < 0) || (pos > longitud)) throw EListOutOfRange(); 
    TNodo *nodoNuevo = new TNodo(elementoNuevo);
    if (!pos) {
      nodoNuevo->Next(primero);
      primero = nodoNuevo;
    }
    else {
      TNodo *cursor  = primero;
      int   contador = 1;
      while (contador < pos) {
        cursor = cursor->Next();
        contador++;
      }
      nodoNuevo->Next(cursor->Next());
      cursor->Next(nodoNuevo);
    }
    longitud++;
  }
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool TListaE::Update(void* valor, int pos) {
  if ((pos < 0) || (pos > longitud)) throw EListOutOfRange();
  Eliminar(pos);
  Insertar(valor, pos);
  return true;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
  void* TListaE::Obtener(int pos) {
    if ((pos < 0) || (pos >= longitud)) throw EListOutOfRange();
    TNodo* cursor = primero;
    for (int i = 0; i < pos; i++)
      cursor = cursor->Next();
    return cursor->Info();
  }
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void TListaE::ParaCada(TFuncionAccion fAccion, void *referencia = NULL)
{
  TNodo* cursor = primero;
  while (cursor) {
    fAccion(cursor, referencia);
    cursor = cursor->Next();
  }
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void* TListaE::PrimeroQueCumple(TFuncionCondicional fCondicion, void *referencia = NULL)
{
  TNodo* cursor = primero;
  bool encontrado = false;
  while (cursor && !encontrado) {
    if (fCondicion(cursor, referencia)) encontrado = true;
    else cursor = cursor->Next();
  }
  return ((encontrado)? cursor->Info():NULL);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void TListaE::TodoQueCumple(TFuncionCondicional fCondicion, TListaE &ListaT, void *referencia = NULL)
{
  TNodo* cursor = primero;
  if (ListaT.Longitud())
    for (int i = 0; i < ListaT.Longitud(); i++) ListaT.Transferir(i);
  while (cursor) {
    if (fCondicion(cursor, referencia))
      ListaT.Anadir(cursor->Info());
    cursor = cursor->Next();
  }
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int TListaE::CuantosCumplen(TFuncionCondicional fCondicion, void *referencia = NULL)
{
  TNodo* cursor = primero;
  int Cantidad  = 0;
  while (cursor) {
    if (fCondicion(cursor, referencia))
      Cantidad++;
    cursor = cursor->Next();
  }
  return Cantidad;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
void TListaE::OrdenarLista(TFuncionCondicional fCondicion, void *referencia = NULL)
{
  for (int i = 0; i < longitud - 1; i++)
    for (int j = i + 1; j < longitud; j++)
      if (fCondicion(PosNodo(i), PosNodo(j))) {
        if (i > j) {
           void* TempInfoI = Transferir(i);
           void* TempInfoJ = Transferir(j);
           Insertar(TempInfoI, j);
           Insertar(TempInfoJ, i);
        }
        else {
           void* TempInfoJ = Transferir(j);
           void* TempInfoI = Transferir(i);
           Insertar(TempInfoJ, i);
           Insertar(TempInfoI, j);
        }
      }
}
//----------------------------------------------------------------------------

 